import json
import threading

from crawler_core.config.config_redis import RedisClient
from crawler_core.constant.constants import Constants


def synchronized(method):
    outer_lock = threading.Lock()
    lock_name = "__" + method.__name__ + "_lock" + "__"

    def sync_method(self, *args, **kws):
        with outer_lock:
            if not hasattr(self, lock_name): setattr(self, lock_name, threading.Lock())
            lock = getattr(self, lock_name)
            with lock:
                return method(self, *args, **kws)

    return sync_method


class RedisSync(object):

    @synchronized
    def refreshEventSearchContextIsOver(self, task_id, is_over):
        context = self.getEventSearchContext(task_id)
        context[Constants.CONTEXT_IS_OVER] = is_over
        self.setEventSearchContext(task_id, context)

    @synchronized
    def refreshEventSearchContextCardNumber(self, task_id, size):
        context = self.getEventSearchContext(task_id)
        total = int(context[Constants.CONTEXT_TOTAL])
        cur_complete = int(context[Constants.CONTEXT_CARD_COMPLETE])
        cur_total = int(context[Constants.CONTEXT_CUR_TOTAL])
        cur_complete += 1
        cur_total += size
        context[Constants.CONTEXT_CARD_COMPLETE] = cur_complete
        context[Constants.CONTEXT_CUR_TOTAL] = cur_total
        if cur_total >= total:
            context[Constants.CONTEXT_IS_OVER] = 1
        self.setEventSearchContext(task_id, context)
        return cur_total, total

    @synchronized
    def addEventAccount(self, corp_code, _type, username, status):
        obj = self.getEventAccount(corp_code, _type)
        if obj:
            obj = self.getJson(obj)
            obj[username] = status
        else:
            obj = {username: status}
        value = self.getJsonStr(obj)
        self.setEventAccount(corp_code, _type, value)

    def getEventSearchContext(self, task_id):
        key = "event:search:context:" + task_id
        value = RedisClient.get(key)
        if not value:
            return None
        return self.getJson(value)

    def setEventSearchContext(self, task_id, context):
        key = "event:search:context:" + task_id
        value = self.getJsonStr(context)
        return RedisClient.set(key, value)

    def getEventAccount(self, corp_code, _type):
        name = "event:account"
        key = corp_code + "@#@" + _type
        value = RedisClient.hget(name, key)
        if value:
            obj = self.getJson(value)
            return obj
        return None

    def setEventAccount(self, corp_code, _type, value):
        name = "event:account"
        key = corp_code + "@#@" + _type
        RedisClient.hset(name, key, value)

    def getJsonStr(self, data):
        return json.dumps(data)

    def getJson(self, str):
        return json.loads(str)
